#习题23 创建一个Person类，包含一个name属性和一个age属性。实现一个方法set_age用于设置age属性，确保年龄不能是负数。
class Person:
    def __init__(self,name,first_name,last_name):
        # self._validate_name(name)
        self.name=name
        self._age=0
        self.first_name=first_name
        self.last_name=last_name
        self.__greet()

    def set_age(self,age):
        if age>0 and age<200:
           self._age=age
        else:
            raise '年龄不能小于0'

    @property
    def age(self):
        return self._age

    @property
    def full_name(self):
        return  f'{self.first_name} {self.last_name}'

    @property
    def is_adult(self):
        # if self._age>=18:
        #     print(self.full_name+'的年龄是满了18岁')
        # raise '年龄未满18岁'
        #三元运算符
        return self._age>=18 if self.age is not None else False

    '''
      私有方法声明: __方法名 ，前面加两个下划线就是私有方法名
      
      私有属性声明: _属性， 前面加个下划线就行私有属性
      
      判断字符串是否包含空格
      '' in name
      name.find(' ')!=-1
      has_space=bool(re.search(r"",name))
    '''
    def _validate_name(self,name):
        #
         if ' ' in name:
             raise '字符串包含空格'
    '''
      声明私有方法，不能被外部调用
    '''
    def __greet(self): # 注意是双下划线
        print(f"Hello, my name is {self.name}!")

    '''
      声明类方法
      @classmethod 装饰器会将类本身作为第一个参数传递给方法，而不是类的实例。按照 Python 的约定，我们通常将这个参数命名为 cls，以明确它代表的是类（class），而不是实例（self）。
     注意：在方法加上了  @classmethod 修饰表明是类方法 ，这样参数不能用self，而是用cls,，我们通常将这个参数命名为 cls，以明确它代表的是类（class），而不是实例（self）
    '''
    # @classmethod
    # def from_string(cls,name_string):
    #     first_name,last_name=name_string.split()
    #     return cls(name_string,first_name,last_name)
    @classmethod
    def from_string(cls, name_string):
        # 现在 cls 变量就代表 Person 类
        first_name, last_name = name_string.split()
        # 使用 cls() 来创建一个新的 Person 实例
        return cls(name_string,first_name, last_name)

    '''
      声明静态方法
      注意：声明静态方法中没有self了
    '''
    @staticmethod
    def is_valid_age(age):
       if age<=0:
            raise '年龄必须大于0'


#习题25 在Person类中添加一个full_name属性，该属性是由first_name和last_name组成的。使用@property装饰器实现该属性。

#习题26 在Person类中添加一个is_adult方法，该方法检查一个人的年龄是否大于或等于18岁。使用@property装饰器将其转换为只读属性。

#习题27 为Person类添加一个私有方法_validate_name，该方法检查名字是否包含空格。在__init__方法中使用这个私有方法验证name。

#习题28 在Person类中添加一个greet方法，该方法打印一条包含名字的问候信息。确保该方法不能被类的外部直接访问。

#习题29 使用@classmethod装饰器在Person类中添加一个类方法from_string，该方法接受一个格式为"first_name last_name"的字符串，并返回一个Person对象。


#习题30 使用@staticmethod装饰器在Person类中添加一个静态方法is_valid_age，该方法接受一个年龄作为参数，并检查该年龄是否有效（即是否为非负整数）。

if __name__ == '__main__':
    # person=Person('张三','张','三')
    # print(person.name)
    # person.set_age(20)
    # #- 定义时，在实例方法的基础上添加 @property 装饰器；并且仅有一个self参数
    # #- 调用时，无需括号
    # print(person.age)
    # print(person.full_name)
    # print(person.is_adult)
    # person.__greet()
    # --- 使用示例 ---
    person = Person.from_string("Alice Smith")
    print(person.full_name)  # 输出: Alice Smith
    print(person.first_name)  # 输出: Alice
    print(person.last_name)  # 输出: Smith

    Person.is_valid_age(-10)